#ifndef GLOBAL_H
#define GLOBAL_H

#include <QHash>
#include <QBitArray>
#include <QVector>
#include <QDebug>

void print(QByteArray tmp);

extern unsigned char host_addr;
extern unsigned char local_addr;



//调试信息开关
#define DEBUG_ON    (1)


//====================================================================================
//====================================================================================
//系统手控点最大数目
#define MAX_NUM_GRA_BTN     (200)

//完整模式下每页手控点的排布
#define BTN_ROWS_PER_PAGE       (4)     //行数
#define NUM_OF_BTN_PER_ROW      (5)     //列数
#define NUM_OF_BTN_PER_PAGE     ((BTN_ROWS_PER_PAGE)*(NUM_OF_BTN_PER_ROW))  //每页总数

//简化模式下每页手控点的排布
#define BTN_ROW         (5)
#define BTN_COL           (8)
#define NUM_OF_BTN      ((BTN_ROW)*(BTN_COL))


//====================================================================================
//====================================================================================
//LED操作模式定义
typedef enum _led_mode
{
    TURN_ON = 0,
    TURN_OFF = 1,
    BLINK = 2,
    BLINK_OFF = 3,
    UNDEFINED = 4
}led_mode;


//====================================================================================
//====================================================================================
/*
*   GraButtonNumAllocation：手控点编号分配类
*   手控点编号维持在1-1800
*   添加手控点时，从最末尾分配新的编号，编号达到1800之后，从前面找出未使用的编号来分配
*   删除手控点，回收编号
*/
class GraButtonNumAllocation
{
public:
    explicit GraButtonNumAllocation():tail(0), item_count(0)
    {
        if(numbers.isEmpty())
        {
            numbers.resize( MAX_NUM_GRA_BTN + 1 );
            numbers.setBit(0,true);
        }
    }
    int allocate_num();
    int get_item_count() const{ return item_count;}
    void updata_tail(int new_tail , int increament );
    void mark_id(int id, bool flag);
    void clear_all();
    void used_num();

private:
    QBitArray numbers;      //比特数组，记录编号分配情况
    int tail;				//上一次分配的编号
    int item_count;			//当前已经添加的手控点总数
};

extern GraButtonNumAllocation num_allocate;



//====================================================================================
//====================================================================================
//手控点编号无效值定义
#define INVALID_MAX_ID      (10000)
#define INVALID_MIN_ID      (-10000)

typedef enum _vector_pos
{
    HEAD = true,
    TAIL = false
}VectorPos;

//记录当前页面下显示的按钮，为翻页服务
class CurrentBtnRcd
{
public:
    explicit CurrentBtnRcd()
    {
        isTheFirstPage=true;
        isTheLastPage=false;
    }
    //添加一个图形元件到当前页面图形元件记录
    bool addOneRecord(int btnID,VectorPos pos,int sys_mode);
    void eraseAllRecord();
    //通过编号判断一个图形元件是否在当前显示的页面
    bool isRecordExist(int btnID);
    //获取当前显示页面中编号最大的图形元件
    int getMaxID();
    //获取当前显示页面中编号最小的图形元件
    int getMinID();
    //获取当前页面显示的按钮数目
    int size(){ return records.size();}

    void setToFisrtPage(bool isFirstPage){ isTheFirstPage = isFirstPage;}
    void setToLastPage(bool isLastPage){ isTheLastPage = isLastPage; }
    bool isFistPage(){ return isTheFirstPage; }
    bool isLastPage(){ return isTheLastPage; }

private:
    QVector<int> records;
    bool isTheFirstPage;
    bool isTheLastPage;
};


//====================================================================================
//      系统工作模式：完整模式 &　简化模式
//====================================================================================
class SysMode
{
public:
    enum{FULL_MODE=0,SIMPLE_MODE=1};
    int getMode();
    void setMode(int _mode = FULL_MODE);
    static SysMode* Instance();

private:
    SysMode():sys_mode(FULL_MODE){}
    ~SysMode(){}
    SysMode(const SysMode&);
    SysMode& operator =(const SysMode& );
    int sys_mode;
};


//====================================================================================
//      手控盘与手控点状态记录类：
//                是否处于总线禁止状态
//                是否处于手控点屏蔽状态
//                是否定义/是否故障/是否启动/是否反馈
//      有手控点相关的状态都通过手控点编号索引
//====================================================================================
class NodeStatus
{
public:
    typedef QHash<unsigned int,unsigned int>::const_iterator const_itr;
    enum
    {
        FORBID_BIT=0x00000001,
        FAULT_BIT=0x00000002,
        START_BIT=0x00000004,
        FEDBACK_BIT=0x00000008,
      };
    static NodeStatus* Instance()
    {
        static NodeStatus _status;
        return &_status;
    }

    // 总线是否允许，允许=true, 禁止=false
    bool isBusAllow(){ return is_bus_allow; }
    // 设置总线允许状态
    void setBusAllow(bool flag = true){ is_bus_allow = flag; }

    //手控点是否定义 true=定义，false=未定义
    bool isNodeDefined(int node_num);

    //手控点是否屏蔽 true=屏蔽，false=未屏蔽
    bool isNodeForbid(int node_num);

    //手控点是否启动 true=启动，false=未启动
    bool isNodeStart(int node_num);

    //手控点是否反馈 true=反馈，false=未反馈
    bool isNodeFedback(int node_num);

    //手控点是否故障 true=故障，false=未故障
    bool isNodeFault(int node_num);

    //设置手控点的状态为：已屏蔽/已故障/已启动/已反馈
    void setNodeStatus(int node_num, unsigned int option);

    //设置手控点的状态为：未屏蔽/未故障/停止/未反馈
    void resetNodeStatus(int node_num, unsigned int option);

    //添加一个记录
    bool add(int node_number, unsigned int status);

    //删除一个记录
    bool remove(int node_number);

    void clear(){node_status_table.clear();}

private:
    NodeStatus():is_bus_allow(true){}
    NodeStatus(const NodeStatus&);
    NodeStatus& operator =(const NodeStatus&);

private:
    bool is_bus_allow;// 总线是否允许
    /*
    key = 手控点编号；
    value：
        bit0 是否屏蔽   1:屏蔽  0:未屏蔽
        bit1 是否故障   1:故障  0:未故障
        bit2 是否启动   1:启动  0:未启动
        bit3 是否反馈   1:反馈  0:未反馈
    */
    QHash<unsigned int,unsigned int> node_status_table;//存储是否启动/反馈/故障等信息
};

#endif // GLOBAL_H
